package de.fhaugsburg.games.boardgames.scrabble.consoleui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

import de.fhaugsburg.games.boardgames.Player;
import de.fhaugsburg.games.boardgames.PlayerMode;
import de.fhaugsburg.games.boardgames.exceptions.GameException;
import de.fhaugsburg.games.boardgames.scrabble.LetterPiece;
import de.fhaugsburg.games.boardgames.scrabble.ScrabbleEngine;
import de.fhaugsburg.games.boardgames.scrabble.ScrabblePlayer;
import de.fhaugsburg.games.boardgames.scrabble.ScrabbleEngine.State;

/**
 * The CommandProcessor handles the use inputs and delegates the other objects.
 * 
 * @author r4smus
 * 
 */
public class CommandProcessor {

	private ScrabbleEngine engine;
	private BoardView boardView;

	public CommandProcessor(ScrabbleEngine engine, BoardView boardView) {
		this.engine = engine;
		this.boardView = boardView;
	}

	/**
	 * A enum for the different types of commands in scrabble.
	 * 
	 * @author r4smus
	 * 
	 */
	private enum Command {
		$ADD, $NEWGAME, $COMMIT, $HELP, $EXIT
	}

	/**
	 * the main method in the scrabble game, with a infinite loop to process the user inputs.
	 * 
	 * @throws GameException
	 */
	public void process() throws GameException {

		String[] input;
		Command command = Command.$EXIT;
		int row;
		int column;
		LetterPiece piece;
		ScrabblePlayer currentPlayer;

		while (true) {

			System.out.println("command: ");

			input = readCommand(); // reads the input from the user

			try {
				command = Command.valueOf(input[0].toUpperCase()); // command from the user, for exmaple NEWGAME, ADD, ...
			} catch (IllegalArgumentException e) {
				System.err.println("wrong command, please try again.");
				continue;
			}

			switch (command) {
			case $NEWGAME:
				newgameOutput();
				resetGame();
				engine.setPlayerMode(input[1].toUpperCase()); // sets the playerMode with a String, which has the value "SP" or "MP"
				System.out.println("INSERT PLAYERNAMES: ");
				input = readCommand();
				engine.initPlayerContainer(input);
			    engine.initCurrentPlayer();
				currentPlayer = engine.getCurrentPlayer();
				boardView.render();
				System.out.println("Current Player: " + currentPlayer.getName() +"\npieces: " +currentPlayer.piecesToString());
				break;

			case $ADD:
				try {
				engine.setState(State.DROPPING);
				piece = LetterPiece.valueOf(input[1].toUpperCase()); // sets the letter from the input[] at the index 1.
				row = parseLetterToInt(input[2].toUpperCase());
				column = Integer.parseInt(input[3]) - 1; // sets the column from the input[] at the index 3.
				currentPlayer = engine.getCurrentPlayer();

				
					engine.setPiece(piece, row, column);
					boardView.render();
					System.out.println("Current Player: " + currentPlayer.getName() +"\npieces: " +currentPlayer.piecesToString());

				} catch (GameException e1) {
					System.err.println(e1.getMessage());
					continue;
				} catch (IllegalArgumentException e2){
					System.err.println("wrong command");
				}
				break;
			case $COMMIT:				
				engine.setState(State.COMMITED);
				currentPlayer = engine.getCurrentPlayer();
				
				System.out.println("Current Player: " + currentPlayer.getName() +"\npieces: " +currentPlayer.piecesToString());
				
				break;


			case $HELP:
				System.out.println("$NEWGAME <SP | MP>                       *start a newgame in the singleplayer- or multiplayermode");
				System.out.println("INSERT PLAYERNAMES: PLAYER1 PLAYER2 ...  *please insert the playernames in this syntax");
				System.out.println("$ADD letter row column                   *put a letter on a specific square");
				System.out.println("$COMMIT                                  *commmit a word");
				System.out.println("$HELP");
				System.out.println("$EXIT                                    *exit the game");
				break;

			case $EXIT:
				System.out.println("exit the game...");
				System.exit(0);
				break;

			default:
				break;
			}

		}

	}

	/**
	 * reads the user input from the console with a bufferedreader and convert him into a string. the string will be split and gets in a String array.
	 * 
	 * @return string[] with the user inputs
	 */
	private String[] readCommand() {
		String input = "";
		String[] inputRefine = new String[10];
		BufferedReader myinput = new BufferedReader(new InputStreamReader(System.in));
		try {
			input = myinput.readLine();
			inputRefine = input.split(" ");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return inputRefine;
	}

	/**
	 * Converts a userinput of a row letter to a integer value of the row.
	 * 
	 * @param s
	 * @return int value of a specific row
	 * @throws GameException 
	 */
	private int parseLetterToInt(String s) throws GameException {
		

		HashMap<String, Integer> hm = new HashMap<String, Integer>();

		String letterSet = "ABCDEFGHIJKLMNO";
		int i = 0;
		for (int j = 0; j < letterSet.length(); j++) {
			hm.put(letterSet.substring(j, j + 1), i++);
		}
		if( ! hm.containsKey(s) ) throw new GameException("wrong row command, please use only letters between A - O.");

		return hm.get(s);

	}

	/**
	 * the logo which is printed to the console when the game starts.
	 */
	private void newgameOutput() {
		System.out.println("------------------------------------------------------------------------------------------------------------------");
		System.out.println("----------------------------------------------------Scrabble------------------------------------------------------");
		System.out.println("------------------------------------------------------------------------------------------------------------------");
	}
	
	private void resetGame(){
		engine = new ScrabbleEngine();
		boardView = new BoardView(engine.getBoard());
	}
	


}
